package com.qiyu.tech.pay.queue.handler;

import com.qiyu.core.cache.redis.app.lock.IDistributionLock;
import com.qiyu.tech.pay.queue.model.DelayTaskInfo;
import com.qiyu.tech.pay.queue.DelayTaskInfoManager;
import com.qiyu.tech.pay.queue.model.DelayTaskSortItem;
import com.qiyu.tech.pay.queue.RedisQueue;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @Author linhao
 * @Date created in 8:47 上午 2021/4/1
 */
@Component
@Slf4j
public class RedisDelayQueueHandler implements Runnable {

    @Resource(name = "redisDelayQueue")
    private RedisQueue<DelayTaskSortItem> redisDelayQueue;
    @Resource(name = "redisReadyQueue")
    private RedisQueue<DelayTaskInfo> redisReadyQueue;
    @Resource
    private IDistributionLock distributionLock;
    @Resource
    private DelayTaskInfoManager delayTaskInfoManager;

    @SneakyThrows
    @Override
    public void run() {
        while (true) {
            Thread.sleep(1000);
            try {
                DelayTaskSortItem delayTaskSortItem= redisDelayQueue.pop();
                if (delayTaskSortItem == null) {
                    continue;
                }
                String lockKey = "pay:notify:dequeue:lock" + delayTaskSortItem.getTaskId();
                try {

                    boolean lockStatus = distributionLock.tryLockTimeOut(lockKey, 3000);
                    if (!lockStatus) {
                        continue;
                    }

                    if(delayTaskSortItem.getExecuteTime() > System.currentTimeMillis()){
                        continue;
                    }

                    DelayTaskInfo delayTaskInfo = delayTaskInfoManager.get(delayTaskSortItem.getTaskId());
                    if(delayTaskInfo == null) {
                        log.error("队列任务有误！taskId is {}",delayTaskSortItem.getTaskId());
                        continue;
                    }

                    if(delayTaskInfo.getExecuteTime() > System.currentTimeMillis()) {
                        continue;
                    }

                    //推入任务到达就绪队列之前需要检查是否符合条件：执行任务时间，任务池和延迟队列任务是否一致，任务id是否一致
                    log.info("推入任务："+delayTaskInfo);
                    redisReadyQueue.put(delayTaskInfo);
                    redisDelayQueue.delete(delayTaskSortItem);
                    delayTaskInfoManager.finishPayNotifyJob(delayTaskInfo);

                }catch (Exception e){
                    log.info("支付的延迟队列出现异常情况1：", e);
                }finally {
                    distributionLock.releaseLock(lockKey);
                }
            } catch (Exception e) {
                log.info("支付的延迟队列出现异常情况2：", e);
            }

        }
    }


}
